#region Using directives

using System;
using System.Collections;
using System.Text;

#endregion

namespace Hanoi.Utils
{
    /// <summary>
    /// FixedSizeStack provides an easy Stack implementation width a fixed size to prevent Stack Overflows in another sense.
    /// It also performs faster and lets you compare a few stacks at the same time.
    /// </summary>
    public class FixedSizeStack: IEnumerable
    {
        private int _size;
        /// <summary>
        /// The maximum size of the stack. When it's reached, it throws a new StackOverflowException while
        /// adding new element.
        /// </summary>
        public int Size
        {
            get { return _size; }
        }

        private int _count;
        /// <summary>
        /// Number of items currently inserted.
        /// </summary>
        public int Count
        {
            get { return _count; }
        }

        private object[] _stack;
	

        public FixedSizeStack(int size)
            : base()
        {
            if (size < 1)
                throw new NotSupportedException("A Stack must have at least one element");

            InitializeMembers(size);
        }

        private void InitializeMembers(int size)
        {
            _size = size;
            _count = 0;
            _stack = new object[_size];
            for (int i = 0; i < _size; i++)
                _stack[i] = null;
        }

        public object Peek()
        {
            int index = _count - 1;
            if (index < 0)
                return null;
            else
                return _stack[index];
        }

        public object Pop()
        {
            int index = _count - 1;
            if (index < 0)
                throw new InvalidOperationException("There is not element on the stack.");
            else
            {
                _count--;
                return _stack[index];
            }
        }

        public void Push(object obj)
        {
            if (_count == _size)
                throw new StackOverflowException();
            else
            {
                _stack[_count] = obj;
                _count++;
            }
        }

        public IEnumerator GetEnumerator()
        {
            return _stack.GetEnumerator();
        }

        public object[] ToArray()
        {
            return (object[])_stack.Clone();
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            for (int i = _size; i > 0; i++)
            {
                object o = _stack[i];
                if (o == null)
                    sb.Append("   |");
                else
                    sb.Append(" " + o.ToString() + " |");
            }

            return sb.ToString();
        }
    }
}
